#!/usr/bin/env python
# -*- coding: utf-8 -*-

#
# This program is free software; you can redistribute it and/or modify  
# it under the terms of the GNU General Public License as published by  
# the Free Software Foundation; either version 2 of the License, or     
# (at your option) any later version.                                   
#                                                                         
# A copy of the license can be found in the license.txt file supplied   
# with this software or at: http://www.gnu.org/copyleft/gpl.html       
#

# 
#  Data Transfer Stack :
#  codec    : None
#  protocol : TextSizeProtocol
#

import sys,time

from spinage.help import logging

from spinage.accessor import Accessor
from spinage.response import RC_OK

from spinage.help.protocol.simpletextsize import SimpleTextSizeProtocolFactory
from spinage.help.protocol.simpletextline import SimpleTextLineProtocolFactory

from spinage.help.zipcodecor import ZipCodecor
from spinage.help.base64codecor import Base64Codecor
from spinage.help.passthrucodecor import PassthruCodecor

#logging.getLogger().setLevel(logging.LEVEL_DEBUG)


IP = '127.0.0.1'
PORT = 4344
TIMEOUT_MS = 10000

if  __name__ == '__main__' :

    from optparse import OptionParser
    parser = OptionParser()
    parser.add_option("", "--codec", dest="codec", type="string", default='',
                        help='codecors, none or more, separated by ","; e.g. "zip", "zip,base64","json","base64"')
    parser.add_option("-p", "--protocol", dest="protocol", type="string", default='textsize',
                        help='communcation protocol, such as "textsize" (default), "textline"')

    parser.add_option("-s", "--msg-size", dest="msg_size", type="int", default=0,
                        help='size of message to send')
    parser.add_option("-t", "--perf-times", dest="perf_times", type="int", default=0,
                        help='round times of performance test')

    parser.add_option("-l", "--logconf", dest="logconfig", type="string",
                        help='path to logging configure file')

    parser.add_option("-d", "--debug", dest="debug", action="store_true", default=False,
                        help='show debug information')

    (options, args) = parser.parse_args()
    if not options.protocol :
        parser.print_help( sys.stdout )
        sys.exit(0)

    if options.logconfig :
        logging.loadConfigure( options.logconfig )

    if options.debug :
        logger = logging.getLogger()
        logger.setLevel(logging.LEVEL_DEBUG)

    ####-----------------------------------------------------------####

    if 'textsize' == options.protocol :
        protocol_factory = SimpleTextSizeProtocolFactory()
    elif 'textline' == options.protocol :
        protocol_factory = SimpleTextLineProtocolFactory()
    else :
        raise RuntimeError,'Unsupport protocol "%s"' % options.protocol

    codecor_list = []
    if options.codec :
        codecor_names = options.codec.split(',')
        for name in codecor_names :
            if 'zip' == name :
                codecor = ZipCodecor()
            elif 'base64' == name :
                codecor = Base64Codecor()
            elif 'passthru' == name :
                codecor = PassthruCodecor()
            else :
                raise RuntimeError, 'Unsupport codecor "%s"' % name
            codecor_list.append( codecor )


    logger = logging.getLogger('EchoClient')
    TIMES = options.perf_times

    c = Accessor()

    c.setProtocolFactory(protocol_factory)

    if codecor_list :
        codec_chain = c.getCodecChain()
        for codecor in codecor_list :
            codec_chain.add( codecor )
            
    request = 'hello,world.'
    response_want = request
    address = (IP, PORT)
    timeout_ms = TIMEOUT_MS

    logger.info(' - calling %s request data:%r ...', address, request)
    status_code,response = c.call(request, address, timeout_ms)
    logger.info('   calling %s response code:%s data:%r .', address, status_code, response)

    if response_want != response :
        logger.error('response is %r, but %r is wanted!', response, response_want)
        sys.exit(1)
    
    if options.msg_size > len(request) :
        request = '-'.join((request, 'A' * (options.msg_size - len(request) - 1)))
        status_code,response = c.call(request, address, timeout_ms)
        if RC_OK != status_code :
            logger.error('fail to detect response message size')
            sys.exit(1)
    record_length = len(request) + len(response)

    if TIMES > 0 :
        logger.info('* performance testing ...')
        count_success = 0
        count_failure = 0
        time_start = time.time()
        for i in xrange(TIMES) :
            status_code,response = c.call(request, address, timeout_ms)
            if RC_OK == status_code :
                count_success += 1
            else :
                count_failure += 1
        time_last = time.time() - time_start
        tps = TIMES / time_last
        bw = tps * record_length / 1048576.0

        logger.info('  test %d times (done:%d fail:%d), last %.2f seconds, tps:%.2f, bw=%.2f MB/s', TIMES, count_success, count_failure, time_last, tps, bw)
        logger.info('* performance testing done.')

    sys.exit(0)

